const { isMainThread, parentPort, workerData } = require('worker_threads')
const mysql = require('mysql2/promise');
const dbhealper = require('../utils/dbhealper');
const axiosUitl = require("../utils/axios");
const { sleep } = require("../utils/utils")
const { HttpProxyAgent } = require('http-proxy-agent');
const proxyCenter = require("./proxy");

if (isMainThread) {
    return
}

const runWorker = async () => {
    setTimeout(() => {
        runWorker()
    }, 4 * 60 * 60 * 1000 + 2000);
    const conn = await mysql.createConnection(dbhealper.config)
    await conn.query("update blum set sync=0 where id>0")

    // 一次10个并行
    let index = 0
    const proxyList = proxyCenter.proxyList
    while (true) {
        await sleep(2000)
        try {
            const step = 20
            let [results, fields] = await conn.query("select * from blum where sync=0 limit ?", [step])
            if (results.length == 0 || results == null) {
                break
            }
            let promises = []
            for (let i = 0; i < results.length; i++) {
                const proxyIndex = index % proxyList.length
                const proxy = proxyList[proxyIndex]
                const element = results[i]
                const unit = new BlumUnit(element, proxy, conn)
                const prms = unit.run()
                promises.push(prms)
                index++
            }
            await Promise.allSettled(promises)
            console.log(Date(), "finished " + index + "..<" + (index + results.length))
        } catch (error) {
            console.error(Date(), error.message)
            continue
        }
    }
    await conn.end();
}

class BlumUnit {
    constructor(tokenInfo, proxyInfo, sqlconn) {
        this.tokenInfo = tokenInfo
        this.proxyInfo = proxyInfo
        this.sqlconn = sqlconn
    }

    getProxy() {
        if (this.proxyInfo == null) {
            return null
        }
        return {
            protocol: "http",
            host: this.proxyInfo.ip,
            port: this.proxyInfo.port,
        }
    }

    async run() {
        try {
            const proxy = axiosUitl.parseProxy(this.proxyInfo)
            const axios = axiosUitl.createAxios(proxy, null)
            let authHeader = {
                authorization: this.tokenInfo.access_token
            }
            // 首先刷新token
            console.log(Date(), "blum start")
            const refreshToken = this.tokenInfo.refresh_token.replace("Bearer ", "")
            const refreshTokenResp = await axios.request("https://gateway.blum.codes/v1/auth/refresh", {
                method: "post",
                data: {
                    refresh: refreshToken
                }
            })
            console.log(Date(), "refreshToken")
            this.tokenInfo.access_token = "Bearer " + refreshTokenResp.data.access
            this.tokenInfo.refresh_token = "Bearer " + refreshTokenResp.data.refresh
            authHeader = {
                authorization: this.tokenInfo.access_token
            }
            // 更新表token
            await this.sqlconn.query("update blum set access_token=?, refresh_token=? where id=?", [this.tokenInfo.access_token, this.tokenInfo.refresh_token, this.tokenInfo.id])
            const balanceResp = await axios.request("https://game-domain.blum.codes/api/v1/user/balance", {
                method: "get",
                headers: authHeader
            })
            const balanceData = balanceResp.data;
            console.log(Date(), "banlance", balanceData)
            // 1.1 balance分数入库
            await this.sqlconn.query("update blum set score=? where game_id=?", [balanceData.availableBalance, this.tokenInfo.game_id])
            // 1.2 任务
            // status: NOT_STARTED->STARTED->READY_FOR_CLAIM->FINISHED
            const taskResp = await axios.request('https://game-domain.blum.codes/api/v1/tasks', {
                method: "get",
                headers: authHeader,
            })
            for (let index = 0; index < taskResp.data.length; index++) {
                const task = taskResp.data[index];
                if (task.status == "NOT_STARTED" && task.type != "PROGRESS_TARGET") {
                    // 开始任务
                    await axios.request(`https://game-domain.blum.codes/api/v1/tasks/${task.id}/start`, {
                        method: "post",
                        headers: authHeader,
                    })
                    console.log("开始任务", task.title)
                }
                if (task.status == "READY_FOR_CLAIM") {
                    // 完成任务
                    await axios.request(`https://game-domain.blum.codes/api/v1/tasks/${task.id}/claim`, {
                        method: "post",
                        headers: authHeader,
                    })
                    console.log("完成任务", task.title)
                }
            }

            // 2. 如果已经开始farming
            if (balanceData.farming != null) {
                const endTime = balanceData.farming.endTime
                const nowResp = await axios.request("https://game-domain.blum.codes/api/v1/time/now", {
                    method: "get",
                    headers: authHeader
                })
                const timeNow = nowResp.data.now;
                if (timeNow > endTime) {
                    // 挖矿结束-claim
                    const claimResp = await axios.request("https://game-domain.blum.codes/api/v1/farming/claim", {
                        method: "post",
                        headers: authHeader
                    })
                    console.log("挖矿claim", claimResp.data)
                    // 开始新的挖矿
                    const farmingResp = await axios.request("https://game-domain.blum.codes/api/v1/farming/start", {
                        method: "post",
                        headers: authHeader
                    })
                    console.log("开始挖矿", farmingResp.data)
                }
            } else {
                // 原来没有挖矿则开始新的挖矿
                const farmingResp = await axios.request("https://game-domain.blum.codes/api/v1/farming/start", {
                    method: "post",
                    headers: authHeader
                })
                console.log("开始挖矿", farmingResp.data)
            }
            // 3. 玩游戏
            // 每次玩一把游戏即可，每天肯定可以消耗完passes
            const playPasses = balanceData.playPasses
            if (playPasses > 0) {
                // await sleep(1000)
                const startResp = await axios.request("https://game-domain.blum.codes/api/v1/game/play", {
                    method: "post",
                    headers: authHeader,
                })
                console.log("Game Start", startResp.data)
                const gameId = startResp.data.gameId
                // 随机等待时间+随机分数
                const rdTime = Math.round((Math.random() * 3)) + 30
                await sleep(rdTime * 1000)
                const rdPoints = Math.round((Math.random() * 20)) + 390
                // 游戏上分
                const endResp = await axios.request("https://game-domain.blum.codes/api/v1/game/claim", {
                    method: "post",
                    headers: authHeader,
                    data: {
                        gameId: gameId,
                        points: rdPoints
                    }
                })
                console.log("Game End with Points: ", rdPoints, endResp.data)
            }
            const balanceResp2 = await axios.request("https://game-domain.blum.codes/api/v1/user/balance", {
                method: "get",
                headers: authHeader
            })
            const balanceData2 = balanceResp2.data;
            console.log(Date(), "blum finished", balanceData2)
            // 1.1 balance分数入库
            await this.sqlconn.query("update blum set score=?, sync=1 where game_id=?", [balanceData2.availableBalance, this.tokenInfo.game_id])
        } catch (error) {
            if (error.response != null) {
                console.error(Date(), error.response)
            } else {
                console.error(error)
            }
        }
    }
}

runWorker();